package com.szms.mobile.check;

import android.content.pm.PackageManager;
import android.media.MediaActionSound;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.ImageCapture;
import androidx.camera.core.ImageCaptureException;
import androidx.camera.core.Preview;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.camera.view.PreviewView;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.camera.core.Camera;
import androidx.fragment.app.FragmentActivity;

import com.google.common.util.concurrent.ListenableFuture;
import com.szms.mobile.BaseFragment;
import com.szms.mobile.MainActivity;
import com.szms.mobile.R;
import com.szms.mobile.common.ThreadPool;
import com.szms.mobile.dto.ResultDto;
import com.szms.mobile.service.Installer;
import com.szms.mobile.service.SysCfgService;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * A simple {@link Fragment} subclass.
 * create an instance of this fragment.
 */
public class PhotoFragment extends BaseFragment {

    private Preview preview;
    private ImageCapture imageCapture;
    private Camera camera;
    //背面摄像头
    private boolean isBackLens;

    //闪光灯
    private boolean isFlash;

    // UI Variable
    private PreviewView viewFinder;
    private ImageView imgCapture, imgFlash, imgSwitchCamera;

    private SeekBar zoomSeekBar;

    private int REQUEST_CODE_PERMISSIONS = 10;

    private final String[] REQUIRED_PERMISSIONS = new String[]{
            "android.permission.CAMERA",
            "android.permission.WRITE_EXTERNAL_STORAGE",
            "android.permission.INTERNET"
    };

    private SysCfgService sysCfgService;

    public PhotoFragment(MainActivity _activity) {
        super(_activity,false);
        sysCfgService = Installer.getInstance(activity).getService(SysCfgService.class);
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.startGetMessage();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_photo, container, false);
    }

    @Override
    public void onResume() {
        super.onResume();
        //this.startGetMessage();
        initVariable();
        initUI();
        checkPermissions();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        this.stopGetMessage();
    }

    public void OpenCamera(){

    }

    private void initVariable() {
        isBackLens = true;
        isFlash = false;
    }

    private void initUI() {
        viewFinder = activity.findViewById(R.id.viewFinder);
        imgCapture = activity.findViewById(R.id.img_capture);
        zoomSeekBar = activity.findViewById(R.id.zoom_seekbar);
        imgFlash = activity.findViewById(R.id.img_flash);
        imgSwitchCamera = activity.findViewById(R.id.img_switch_camera);

        imgCapture.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                capture();
            }
        });
        imgFlash.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                isFlash = !isFlash;
                startCamera();
            }
        });
        imgSwitchCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                isBackLens = !isBackLens;
                startCamera();
            }
        });

        zoomSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (camera != null) {
                    float zoomRatio = progress / 10.0f; // 0 to 10 scale
                    camera.getCameraControl().setZoomRatio(zoomRatio);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
            }
        });
    }

    private boolean allPermissionsGranted() {
        for (String permission : REQUIRED_PERMISSIONS) {
            if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    void checkPermissions() {
        if (allPermissionsGranted()) {
            startCamera();
        } else {
            ActivityCompat.requestPermissions(activity, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
        }
    }

    /**
     * 启动相机，开启预览
     */
    void startCamera() {
        ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(activity);
        cameraProviderFuture.addListener(new Runnable() {
            @Override
            public void run() {
                try {
                    // Used to bind the lifecycle of cameras to the lifecycle owner
                    ProcessCameraProvider cameraProvider = cameraProviderFuture.get();

                    // Preview
                    preview = new Preview.Builder()
                            .build();
                    // Select back camera
                    CameraSelector cameraSelector = new CameraSelector.Builder()
                            .requireLensFacing(isBackLens ? CameraSelector.LENS_FACING_BACK : CameraSelector.LENS_FACING_FRONT)
                            .build();

                    // Image Capture
                    int flashMode = ImageCapture.FLASH_MODE_OFF;
                    if (isBackLens && isFlash) {
                        flashMode = ImageCapture.FLASH_MODE_ON;
                    }
                    imageCapture = new ImageCapture.Builder()
                            .setFlashMode(flashMode)
                            .build();

                    // Unbind use cases before rebinding
                    cameraProvider.unbindAll();
                    camera = cameraProvider.bindToLifecycle(activity, cameraSelector, preview, imageCapture);
                    camera.getCameraControl().setZoomRatio(zoomSeekBar.getProgress()/10.0f);
                    preview.setSurfaceProvider(viewFinder.getSurfaceProvider());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, ContextCompat.getMainExecutor(activity));
    }

    /**
     * 拍摄
     */
    void capture() {
        shootSound();

        String filename = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        File file = new File(Environment.getExternalStorageDirectory() , filename + ".jpg");
        if(!file.exists()){
            try {
                file.createNewFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        // Create output options object which contains file + metadata
        ImageCapture.OutputFileOptions outputOptions = new ImageCapture.OutputFileOptions.Builder(file).build();

        // Setup image capture listener which is triggered after photo has
        // been taken
        imageCapture.takePicture(
                outputOptions,
                ContextCompat.getMainExecutor(activity),
                new ImageCapture.OnImageSavedCallback() {
                    @Override
                    public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
//                        String msg = "Photo capture succeeded: " + file.getAbsolutePath();
//                        Toast.makeText(activity.getBaseContext(), msg,Toast.LENGTH_LONG).show();

                        ThreadPool.getInstance().execute(()->transferImage(file));
                    }

                    @Override
                    public void onError(@NonNull ImageCaptureException exception) {
                        //Log.e(TAG, exception.getLocalizedMessage());
                    }
                }
        );
    }

    public void shootSound() {
        MediaActionSound sound = new MediaActionSound();
        sound.play(MediaActionSound.SHUTTER_CLICK);
    }


    public void transferImage(File file){
        ResultDto<String> hostRe = sysCfgService.getHost();
        ResultDto<Integer> portRe = sysCfgService.getPort();
        if (!hostRe.isSuccess()){
            Toast.makeText(activity.getBaseContext(),hostRe.getMessage(),Toast.LENGTH_LONG);
            return;
        }
        if (!portRe.isSuccess()){
            Toast.makeText(activity.getBaseContext(),portRe.getMessage(),Toast.LENGTH_LONG);
            return;
        }
        String host = hostRe.getData();
        Integer port = portRe.getData();

        try (
                Socket socket = new Socket(host, port);
                BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
                FileInputStream inputStream = new FileInputStream(file)
        ) {
            //写文件名
            byte[] headerBuffer = new byte[1024];
            byte[] nameBytes = file.getName().getBytes();
            for(int i=0;i<nameBytes.length;i++){
                headerBuffer[i]=nameBytes[i];
            }
            outputStream.write(headerBuffer,0,headerBuffer.length);

            //写内容
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            System.out.println("File sent.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private Thread getMessageThread;

    /**
     * 开始获取消息
     */
    public void startGetMessage(){
        if (getMessageThread==null){
            getMessageRun = true;
            getMessageThread = new Thread(this::getMessage);
            getMessageThread.start();
            return;
        }
        if (getMessageRun==false){
            try{
                if (getMessageThread!=null){
                    if (getMessageThread.getState().equals(Thread.State.RUNNABLE)){
                        getMessageThread.start();
                    }
                }
            }catch (Exception ex){

            }
            getMessageRun = true;
            getMessageThread = new Thread(this::getMessage);
            getMessageThread.start();
        }
    }

    /**
     * 停止获取消息
     */
    public void stopGetMessage(){
        getMessageRun = false;
    }

    boolean getMessageRun = true;
    private void getMessage()  {

        ResultDto<String> hostRe = sysCfgService.getHost();
        ResultDto<Integer> portRe = sysCfgService.getPort();
        if (!hostRe.isSuccess()){
            Toast.makeText(activity.getBaseContext(),hostRe.getMessage(),Toast.LENGTH_LONG);
            return;
        }
        if (!portRe.isSuccess()){
            Toast.makeText(activity.getBaseContext(),portRe.getMessage(),Toast.LENGTH_LONG);
            return;
        }
        String host = hostRe.getData();
        Integer port = portRe.getData();

        while (getMessageRun){
           try(Socket socket = new Socket(host, port);
               BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream())
           ){
                socket.setSoTimeout(5000);

                byte[] headerBuffer = new byte[1024];
                byte[] orderBytes = "getcheckresult".getBytes();
                for(int i=0;i<orderBytes.length;i++){
                    headerBuffer[i]=orderBytes[i];
                }
                outputStream.write(headerBuffer,0,headerBuffer.length);
                outputStream.flush();

                Thread.sleep(200);

                // 接收服务器返回的消息
               BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
               byte[] receiveBuffer = new byte[inputStream.available()];
               int i= inputStream.read(receiveBuffer);
               String response = new String(receiveBuffer);

               if (response!=null && response.length()>0){

                   // 在主线程中运行 Toast
                   if (getActivity() != null) {
                       getActivity().runOnUiThread(new Runnable() {
                           @Override
                           public void run() {
                               Toast.makeText(getActivity(), response, Toast.LENGTH_LONG).show();
                           }
                       });
                   }
               }

               Thread.sleep(1000);
            }catch (Exception ex){

            }
        }
    }
}